package org.oschina.api.user.user.service;

import java.util.List;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.oschina.Config;
import org.oschina.Constants;
import org.oschina.Message;
import org.oschina.Module;
import org.oschina.ResultUtil;
import org.oschina.api.BaseService;
import org.oschina.api.manage.config.service.ConfigService;
import org.oschina.api.user.follow.service.UserFollowService;
import org.oschina.api.user.role.service.UserRoleTypeService;
import org.oschina.api.user.user.UserType;
import org.oschina.api.user.user.dao.UserDAO;
import org.oschina.api.user.user.model.User;
import org.oschina.api.user.user.vo.UserHomeAccessVo;
import org.oschina.api.user.user.vo.UserMessageVo;
import org.oschina.api.user.user.vo.UserSearchVo;
import org.oschina.api.user.user.vo.UserVo;
import org.oschina.bean.Pager;
import org.oschina.bean.Result;
import org.oschina.helper.email.IEMailHelper;
import org.oschina.plugin.PluginType;
import org.oschina.plugin.PluginHelper;
import org.oschina.security.AuthenticationInfo;
import org.oschina.security.ISecurity;
import org.oschina.security.annotation.Require;
import org.oschina.security.impl.PasswordErrorException;
import org.oschina.security.impl.UserIsOnlineException;
import org.oschina.security.impl.UserNotFoundException;
import org.oschina.api.index.service.IndexService;
import org.oschina.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService extends BaseService {

	@Autowired
	private UserDAO userDAO;
	@Autowired
	private UserRoleTypeService roleTypeService;
	@Autowired
	private PluginHelper pluginHelper;
	@Autowired
	private IndexService indexService;
	@Autowired
	private ConfigService configService;
	@Autowired
	private UserFollowService followService;
	@Autowired
	private ISecurity security;
	@Autowired
	private IEMailHelper emailHelper;
	
	/**
	 * 认证
	 * @param identity
	 * @return
	 */
	public Result registerCheck(String identity)
	{
		User user=_findByRegisterIdentityAndType(identity,UserType.CHECK);
		if(user==null)
			return ResultUtil.getFailure(Message.ERROR_DATA_ERROR);
		
		_updateType(user.getId(),UserType.SIMPLE);
		return ResultUtil.getSuccess(Message.get(Message.REGISTER_CHECK_SUCCESS, user.getUsername()));
	}
	
	/**
	 * 更新密码
	 * @param oldPassword
	 * @param newPassword
	 * @return
	 */
	@Require
	public Result updatePassword(String oldPassword,String newPassword)
	{
		if(oldPassword.equals(newPassword))
			return ResultUtil.getFailure(Message.ERROR_DATA_ERROR);
		
		User user=getAuthenticationInfo(getToken());
		
		if(!user.getPassword().equals(security.passwordFormat(oldPassword)))
			return ResultUtil.getFailure(Message.USER_UPDATE_PASSWORD_FAILURE_SOURCE_PASSWORD_ERROR);
		
		_updatePassword(user, security.passwordFormat(newPassword));
		return ResultUtil.getSuccess(Message.UPDATE_SUCCESS);
	}
	
	/**
	 * 编辑
	 * @param user
	 * @return
	 */
	@Require
	public Result edit(User user)
	{
		User loginUser=getAuthenticationInfo(getToken());
		UserVo byName=_findVoByUsernameAndType(user.getUsername(),UserType.SIMPLE);
		if(byName!=null && !byName.getId().equals(loginUser.getId()))
			return ResultUtil.getFailure(Message.USER_EDIT_USERNAME_IS_EXIST);
		
		user.setId(loginUser.getId());
		_edit(user);
		return ResultUtil.getSuccess(Message.UPDATE_SUCCESS_DELAY);
	}
	
	/**
	 * 用户首页
	 * @param id
	 * @return
	 */
	public UserHomeAccessVo homeAccess(int id)
	{
		UserMessageVo userMessage=getMessageById(id);
		if(userMessage==null)
			return null;
		
		UserHomeAccessVo userHomeAccessVo=new UserHomeAccessVo();
		userHomeAccessVo.setUser(userMessage);
		userHomeAccessVo.setFollow(followService.findVoBySource(id, 0));
		userHomeAccessVo.setFans(followService.findVoByTarget(id, 0));
		return userHomeAccessVo;
	}
	
	/**
	 * 注册
	 * @param account
	 * @param password
	 * @return
	 */
	public Result register(String account,String password)
	{
		if(_findByAccount(account)!=null)
			return ResultUtil.getFailure(Message.REGISTER_ERROR_USER_IS_EXIST);
		
		if(_isCheck())
		{
			String identity=_getRegisterIdentity();
			String title=_getIdentityTitle();
			String content=_getIdentityContent();
			content=StringUtils.replaceEach(content, new String[]{"{IDENTITY}"}, new String[]{content});
			
			emailHelper.send(title, content, account);
			
			_create(account,password,UserType.CHECK,identity,getIp());
			return ResultUtil.getFailure(Message.get(Message.REGISTER_FAILURE_IS_CHECK, account));
		}
		else
		{
			_create(account,password,UserType.SIMPLE,null,getIp());
			return ResultUtil.getSuccess(Message.REGISTER_SUCCESS);
		}
	}
	private String _getIdentityTitle()
	{
		return (String) configService.getValueById(Config.CONFIG_24, String.class);
	}
	private String _getIdentityContent()
	{
		return (String) configService.getValueById(Config.CONFIG_25, String.class);
	}
	
	/**
	 * 登录
	 * @param account
	 * @param password
	 * @return
	 */
	public Result login(String account,String password)
	{
		AuthenticationInfo authenticationInfo=new AuthenticationInfo();
		authenticationInfo.setUsername(account);
		authenticationInfo.setPassword(password);
		
		try
		{
			pluginHelper.execute(PluginType.LOGIN_BEFORE, authenticationInfo);
			security.login(authenticationInfo);
			pluginHelper.execute(PluginType.LOGIN_AFTER, authenticationInfo);
			return ResultUtil.getSuccess(authenticationInfo.getToken());
		}
		catch (UserNotFoundException e)
		{
			return ResultUtil.getFailure(Message.LOGIN_ERROR_USER_NOT_FOUND);
		}
		catch (PasswordErrorException e)
		{
			return ResultUtil.getFailure(Message.LOGIN_ERROR_PASSWORD_ERROR);
		}
		catch (UserIsOnlineException e)
		{
			return ResultUtil.getFailure(Message.LOGIN_ERROR_USER_IS_ONLINE);
		}
	}
	
	/**
	 * 登出
	 * @return
	 */
	@Require
	public Result logout()
	{
		if(!security.logout(getToken()))
			return ResultUtil.getFailure(Message.LOGOUT_FAILURE);
		
		return ResultUtil.getSuccess(Message.LOGOUT_SUCCESS);
	}
	
	/**
	 * 根据令牌获得信息
	 * @return
	 */
	@Require
	public UserVo getMessageByToken()
	{
		return _toVo(getAuthenticationInfo(getToken()));
	}
	
	/**
	 * 根据ID返回信息
	 * @param id
	 * @return
	 */
	public UserMessageVo getMessageById(int id)
	{
		UserVo userVo=_findVoById(id);
		if(userVo==null)
			return null;
		
		User loginUser=getAuthenticationInfo(getToken());
		UserMessageVo userMessageVo=new UserMessageVo();
		userMessageVo.setUser(userVo);
		
		if(loginUser!=null)
		{
			userMessageVo.setFollow(followService._isFollow(loginUser.getId(), userVo.getId()));
		}
		else
		{
			userMessageVo.setFollow(false);
		}
		
		return userMessageVo;
	}
	
	/**
	 * 搜索
	 * @param account
	 * @param username
	 * @param pn
	 * @return
	 */
	@Require(authorization=Module.MODULE_59)
	public Pager<UserSearchVo> search(String account,String username,int pn)
	{
		Pager<UserSearchVo> pager=new Pager(pn,_getCountByAccountAndUsername(account, username),_getPageCount(),null);
		if(pager.getData_sum()>0)
			pager.setData(_search(account,username,pager.getStart(),pager.getPage_count()));
		return pager;
	}
	
	/**
	 * 更新角色
	 * @param id
	 * @param role
	 * @return
	 */
	@Require(authorization=Module.MODULE_59)
	public Result updateRole(int id,int role)
	{
		if(_findVoById(id)==null || roleTypeService.findById(role)==null)
			return ResultUtil.getFailure(Message.ERROR_DATA_ERROR);
		
		_updateRole(id,role);
		return ResultUtil.getSuccess(Message.UPDATE_SUCCESS);
	}
	
	/**
	 * 踢下线
	 * @param id
	 * @return
	 */
	@Require(authorization=Module.MODULE_59)
	public Result kick(int id)
	{
		_clearToken(id);
		if(userDAO.isOnline(id))
			userDAO.refreshLastPostCache(id, 0);
		return ResultUtil.getSuccess(Message.OPERATION_SUCCESS);
	}
	
	/**
	 * 根据账号和类型返回
	 * @param account
	 * @return
	 */
	private User _findByAccountAndType(String account,int type)
	{
		return userDAO.findByAccountAndType(account,type);
	}
	
	/**
	 * 根据账号返回
	 * @param account
	 * @return
	 */
	private User _findByAccount(String account)
	{
		return userDAO.findByAccount(account);
	}
	
	public User getAuthenticationInfo(String token)
	{
		return (User)security.getAuthenticationInfo(token);
	}
	
	/**
	 * 根据角色更新
	 * @param source
	 * @param target
	 * @return
	 */
	public int _updateRoleByRole(int source,int target)
	{
		return userDAO.updateRoleByRole(source, target);
	}
	
	/**
	 * 根据ID返回
	 * @param id
	 * @return
	 */
	public UserVo _findVoById(int id)
	{
		return userDAO.findVoById(id);
	}
	
	/**
	 * 更新关注数量_加
	 * @param id
	 * @param count
	 */
	public void _updateFollowCount_plus(UserVo user)
	{
		_updateFollowCount(user.getId(), 1);
	}
	
	/**
	 * 更新关注数量_减
	 * @param id
	 * @param count
	 */
	public void _updateFollowCount_minus(UserVo user)
	{
		_updateFollowCount(user.getId(), -1);
	}
	
	/**
	 * 更新粉丝数量_加
	 * @param id
	 * @param count
	 */
	public void _updateFansCount_plus(UserVo user)
	{
		_updateFansCount(user.getId(), 1);
	}
	
	/**
	 * 更新粉丝数量_减
	 * @param id
	 * @param count
	 */
	public void _updateFansCount_minus(UserVo user)
	{
		_updateFansCount(user.getId(), -1);
	}
	
	/**
	 * 搜索
	 * @param account
	 * @param username
	 * @param first
	 * @param max
	 * @return
	 */
	private List<UserSearchVo> _search(String account,String username,int first,int max)
	{
		return userDAO.search(account, username, first, max);
	}
	
	/**
	 * 返回数量
	 * @param account
	 * @param username
	 * @return
	 */
	private int _getCountByAccountAndUsername(String account,String username)
	{
		return userDAO.getCountByAccountAndUsername(account, username);
	}
	
	/**
	 * 根据用户名和类型返回
	 * @param username
	 * @return
	 */
	public UserVo _findVoByUsernameAndType(String username,int type)
	{
		return userDAO.findVoByUsernameAndType(username,type);
	}
	
	/**
	 * 根据注册验证返回 只返回ID,用户名,密码,角色
	 * @param account
	 * @return
	 */
	private User _findByRegisterIdentityAndType(String identity,int type)
	{
		return userDAO.findByRegisterIdentityAndType(identity,type);
	}
	
	/**
	 * 清空令牌
	 * @param id
	 * @return
	 */
	private int _clearToken(int id)
	{
		return userDAO.clearToken(id);
	}
	
	/**
	 * 更新类型
	 * @param id
	 * @param type
	 * @return
	 */
	private int _updateType(int id,int type)
	{
		return userDAO.updateType(id, type);
	}
	
	/**
	 * 更新密码
	 * @param id
	 * @param password
	 * @return
	 */
	private int _updatePassword(User user,String password)
	{
		return userDAO.updatePassword(user.getId(), password);
	}
	
	/**
	 * 编辑
	 * @param user
	 * @return
	 */
	private int _edit(User user)
	{
		return userDAO.edit(user);
	}
	
	/**
	 * 更新角色
	 * @param id
	 * @param role
	 * @return
	 */
	private int _updateRole(int id,int role)
	{
		return userDAO.updateRole(id, role);
	}
	
	/**
	 * 创建
	 * @param account
	 * @param password
	 * @param type
	 * @param registerIdentity
	 * @param ip
	 * @return
	 */
	private User _create(String account,String password,int type,String registerIdentity,String ip)
	{
		User user=new User();
		user.setId(_getIndex());
		user.setAccount(account);
		user.setUsername(account);
		user.setPassword(security.passwordFormat(password));
		user.setHeadphoto(_getDefaultHeadphoto());
		user.setSignature(_getDefaultSignature());
		user.setType(type);
		user.setRole(_getDefaultRole());
		user.setFollow_count(0);
		user.setFans_count(0);
		user.setOnline(false);
		user.setRegister_identity(registerIdentity);
		user.setRegister_ip(ip);
		user.setRegister_time(DateUtil.now());
		return userDAO.create(user);
	}
	
	/**
	 * 更新关注数量
	 * @param id
	 * @param count
	 */
	private void _updateFollowCount(int id,int count)
	{
		userDAO.updateFollowCount(id, count);
	}
	
	/**
	 * 更新粉丝数量
	 * @param id
	 * @param count
	 */
	private void _updateFansCount(int id,int count)
	{
		userDAO.updateFansCount(id, count);
	}
	
	public UserVo getVo(String token)
	{
		return _toVo(getAuthenticationInfo(token));
	}
	
	public UserVo _toVo(User user)
	{
		if(user==null)
			return null;
		
		return _findVoById(user.getId());
	}
	
	private int _getIndex()
	{
		return indexService.getMajorById(Constants.INDEX_USER);
	}
	
	private int _getDefaultRole()
	{
		return roleTypeService.getDefault().getId();
	}
	
	private String _getDefaultHeadphoto()
	{
		return (String) configService.getValueById(Config.CONFIG_5, String.class);
	}
	
	private String _getDefaultSignature()
	{
		return (String)configService.getValueById(Config.CONFIG_18, String.class);
	}
	
	private int _getPageCount()
	{
		return (Integer)configService.getValueById(Config.CONFIG_22, Integer.class);
	}
	
	private boolean _isCheck()
	{
		return (Boolean)configService.getValueById(Config.CONFIG_23,Boolean.class);
	}
	
	private String _getRegisterIdentity()
	{
		return RandomStringUtils.randomAlphabetic(20);
	}
}